home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / net_udp.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  10KB  |  415 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_udp.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <netdb.h>
  28. #include <sys/param.h>
  29. #include <sys/ioctl.h>
  30. #include <errno.h>
  31.  
  32. #ifdef __sun__
  33. #include <sys/filio.h>
  34. #endif
  35.  
  36. #ifdef NeXT
  37. #include <libc.h>
  38. #endif
  39.  
  40. extern int gethostname (char *, int);
  41. extern int close (int);
  42.  
  43. extern cvar_t hostname;
  44.  
  45. static int net_acceptsocket = -1;        // socket for fielding new connections
  46. static int net_controlsocket;
  47. static int net_broadcastsocket = 0;
  48. static struct qsockaddr broadcastaddr;
  49.  
  50. static unsigned long myAddr;
  51.  
  52. #include "net_udp.h"
  53.  
  54. //=============================================================================
  55.  
  56. int UDP_Init (void)
  57. {
  58.     struct hostent *local;
  59.     char    buff[MAXHOSTNAMELEN];
  60.     struct qsockaddr addr;
  61.     char *colon;
  62.     
  63.     if (COM_CheckParm ("-noudp"))
  64.         return -1;
  65.  
  66.     // determine my name & address
  67.     gethostname(buff, MAXHOSTNAMELEN);
  68.     local = gethostbyname(buff);
  69.     myAddr = *(int *)local->h_addr_list[0];
  70.  
  71.     // if the quake hostname isn't set, set it to the machine name
  72.     if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  73.     {
  74.         buff[15] = 0;
  75.         Cvar_Set ("hostname", buff);
  76.     }
  77.  
  78.     if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
  79.         Sys_Error("UDP_Init: Unable to open control socket\n");
  80.  
  81.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  82.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  83.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  84.  
  85.     UDP_GetSocketAddr (net_controlsocket, &addr);
  86.     Q_strcpy(my_tcpip_address,  UDP_AddrToString (&addr));
  87.     colon = Q_strrchr (my_tcpip_address, ':');
  88.     if (colon)
  89.         *colon = 0;
  90.  
  91.     Con_Printf("UDP Initialized\n");
  92.     tcpipAvailable = true;
  93.  
  94.     return net_controlsocket;
  95. }
  96.  
  97. //=============================================================================
  98.  
  99. void UDP_Shutdown (void)
  100. {
  101.     UDP_Listen (false);
  102.     UDP_CloseSocket (net_controlsocket);
  103. }
  104.  
  105. //=============================================================================
  106.  
  107. void UDP_Listen (qboolean state)
  108. {
  109.     // enable listening
  110.     if (state)
  111.     {
  112.         if (net_acceptsocket != -1)
  113.             return;
  114.         if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
  115.             Sys_Error ("UDP_Listen: Unable to open accept socket\n");
  116.         return;
  117.     }
  118.  
  119.     // disable listening
  120.     if (net_acceptsocket == -1)
  121.         return;
  122.     UDP_CloseSocket (net_acceptsocket);
  123.     net_acceptsocket = -1;
  124. }
  125.  
  126. //=============================================================================
  127.  
  128. int UDP_OpenSocket (int port)
  129. {
  130.     int newsocket;
  131.     struct sockaddr_in address;
  132.     qboolean _true = true;
  133.  
  134.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  135.         return -1;
  136.  
  137.     if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
  138.         goto ErrorReturn;
  139.  
  140.     address.sin_family = AF_INET;
  141.     address.sin_addr.s_addr = INADDR_ANY;
  142.     address.sin_port = htons(port);
  143.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  144.         goto ErrorReturn;
  145.  
  146.     return newsocket;
  147.  
  148. ErrorReturn:
  149.     close (newsocket);
  150.     return -1;
  151. }
  152.  
  153. //=============================================================================
  154.  
  155. int UDP_CloseSocket (int socket)
  156. {
  157.     if (socket == net_broadcastsocket)
  158.         net_broadcastsocket = 0;
  159.     return close (socket);
  160. }
  161.  
  162.  
  163. //=============================================================================
  164. /*
  165. ============
  166. PartialIPAddress
  167.  
  168. this lets you type only as much of the net address as required, using
  169. the local network components to fill in the rest
  170. ============
  171. */
  172. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  173. {
  174.     char buff[256];
  175.     char *b;
  176.     int addr;
  177.     int num;
  178.     int mask;
  179.     int run;
  180.     int port;
  181.     
  182.     buff[0] = '.';
  183.     b = buff;
  184.     strcpy(buff+1, in);
  185.     if (buff[1] == '.')
  186.         b++;
  187.  
  188.     addr = 0;
  189.     mask=-1;
  190.     while (*b == '.')
  191.     {
  192.         b++;
  193.         num = 0;
  194.         run = 0;
  195.         while (!( *b < '0' || *b > '9'))
  196.         {
  197.           num = num*10 + *b++ - '0';
  198.           if (++run > 3)
  199.               return -1;
  200.         }
  201.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  202.             return -1;
  203.         if (num < 0 || num > 255)
  204.             return -1;
  205.         mask<<=8;
  206.         addr = (addr<<8) + num;
  207.     }
  208.     
  209.     if (*b++ == ':')
  210.         port = Q_atoi(b);
  211.     else
  212.         port = net_hostport;
  213.  
  214.     hostaddr->sa_family = AF_INET;
  215.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  216.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  217.     
  218.     return 0;
  219. }
  220. //=============================================================================
  221.  
  222. int UDP_Connect (int socket, struct qsockaddr *addr)
  223. {
  224.     return 0;
  225. }
  226.  
  227. //=============================================================================
  228.  
  229. int UDP_CheckNewConnections (void)
  230. {
  231.     unsigned long    available;
  232.  
  233.     if (net_acceptsocket == -1)
  234.         return -1;
  235.  
  236.     if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
  237.         Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
  238.     if (available)
  239.         return net_acceptsocket;
  240.     return -1;
  241. }
  242.  
  243. //=============================================================================
  244.  
  245. int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  246. {
  247.     int addrlen = sizeof (struct qsockaddr);
  248.     int ret;
  249.  
  250.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  251.     if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
  252.         return 0;
  253.     return ret;
  254. }
  255.  
  256. //=============================================================================
  257.  
  258. int UDP_MakeSocketBroadcastCapable (int socket)
  259. {
  260.     int                i = 1;
  261.  
  262.     // make this socket broadcast capable
  263.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  264.         return -1;
  265.     net_broadcastsocket = socket;
  266.  
  267.     return 0;
  268. }
  269.  
  270. //=============================================================================
  271.  
  272. int UDP_Broadcast (int socket, byte *buf, int len)
  273. {
  274.     int ret;
  275.  
  276.     if (socket != net_broadcastsocket)
  277.     {
  278.         if (net_broadcastsocket != 0)
  279.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  280.         ret = UDP_MakeSocketBroadcastCapable (socket);
  281.         if (ret == -1)
  282.         {
  283.             Con_Printf("Unable to make socket broadcast capable\n");
  284.             return ret;
  285.         }
  286.     }
  287.  
  288.     return UDP_Write (socket, buf, len, &broadcastaddr);
  289. }
  290.  
  291. //=============================================================================
  292.  
  293. int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  294. {
  295.     int ret;
  296.  
  297.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  298.     if (ret == -1 && errno == EWOULDBLOCK)
  299.         return 0;
  300.     return ret;
  301. }
  302.  
  303. //=============================================================================
  304.  
  305. char *UDP_AddrToString (struct qsockaddr *addr)
  306. {
  307.     static char buffer[22];
  308.     int haddr;
  309.  
  310.     haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  311.     sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
  312.     return buffer;
  313. }
  314.  
  315. //=============================================================================
  316.  
  317. int UDP_StringToAddr (char *string, struct qsockaddr *addr)
  318. {
  319.     int ha1, ha2, ha3, ha4, hp;
  320.     int ipaddr;
  321.  
  322.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  323.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  324.  
  325.     addr->sa_family = AF_INET;
  326.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  327.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  328.     return 0;
  329. }
  330.  
  331. //=============================================================================
  332.  
  333. int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
  334. {
  335.     int addrlen = sizeof(struct qsockaddr);
  336.     unsigned int a;
  337.  
  338.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  339.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  340.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  341.     if (a == 0 || a == inet_addr("127.0.0.1"))
  342.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  343.  
  344.     return 0;
  345. }
  346.  
  347. //=============================================================================
  348.  
  349. int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
  350. {
  351.     struct hostent *hostentry;
  352.  
  353.     hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  354.     if (hostentry)
  355.     {
  356.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  357.         return 0;
  358.     }
  359.  
  360.     Q_strcpy (name, UDP_AddrToString (addr));
  361.     return 0;
  362. }
  363.  
  364. //=============================================================================
  365.  
  366. int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
  367. {
  368.     struct hostent *hostentry;
  369.  
  370.     if (name[0] >= '0' && name[0] <= '9')
  371.         return PartialIPAddress (name, addr);
  372.     
  373.     hostentry = gethostbyname (name);
  374.     if (!hostentry)
  375.         return -1;
  376.  
  377.     addr->sa_family = AF_INET;
  378.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  379.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  380.  
  381.     return 0;
  382. }
  383.  
  384. //=============================================================================
  385.  
  386. int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  387. {
  388.     if (addr1->sa_family != addr2->sa_family)
  389.         return -1;
  390.  
  391.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  392.         return -1;
  393.  
  394.     if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  395.         return 1;
  396.  
  397.     return 0;
  398. }
  399.  
  400. //=============================================================================
  401.  
  402. int UDP_GetSocketPort (struct qsockaddr *addr)
  403. {
  404.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  405. }
  406.  
  407.  
  408. int UDP_SetSocketPort (struct qsockaddr *addr, int port)
  409. {
  410.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  411.     return 0;
  412. }
  413.  
  414. //=============================================================================
  415.